package cn.tonyandmoney.voicenotes.notes.model;

import android.annotation.SuppressLint;
import android.os.SystemClock;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;

import cn.tonyandmoney.baidu.bus.SpeechBus;
import cn.tonyandmoney.voicenotes.notes.config.RecogParams;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * 保存录音文件,
 * 根据实际要求，实现单文件长度设置，先保存到文件，最后通过对音频文件的裁剪
 * 实现单文件最大长度设置结果，在保存过程中实现长度设置，将会增加代码负责度
 * 给后续处理带来更多麻烦
 */
public class RecordModel implements ObservableOnSubscribe<RecordModel.RecordData>,
        Consumer<RecordModel.RecordData>, Disposable {
    private final String TAG = "RecordModel";

    private final ArrayBlockingQueue<RecordData> mDataList = new ArrayBlockingQueue<>(4096);
    private BufferedOutputStream outputStream;
    private Disposable mDisposable;
    private volatile File mFile;  //这个是一个共享变量
    private final Object lock;

    RecordModel(String filename, Object lock) throws IOException {
        this.lock = lock;
        String parent = RecogParams.Companion.getMRoot();
        File parentFile = new File(parent + "Records");
        if (!parentFile.exists()) parentFile.mkdirs();
        mFile = new File(parentFile, filename);
        if (!mFile.exists()) mFile.createNewFile();
    }

    public File getFile() {
        return mFile;
    }

    /**
     * 开始的时候同时开启一个定时器，定时的改变文件名称
     *
     * @return 取消订阅接口
     */
    @SuppressLint("CheckResult")
    public void start() {
        mDisposable = Observable.create(this)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(this);
    }

    @Override
    public void accept(RecordData data) {
        synchronized (lock) {
            if (outputStream == null) return;
            try {
                outputStream.write(data.bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void createNewFile() throws IOException {
        synchronized (lock) {
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
            outputStream = new BufferedOutputStream(new FileOutputStream(mFile));
        }
    }


    @Override
    public void subscribe(ObservableEmitter<RecordData> emitter) {
        try {
            createNewFile();
            while (!emitter.isDisposed()) {
                emitter.onNext(mDataList.take());
            }
            onComplete();
        } catch (Exception e) {
            if (mDisposable != null && !mDisposable.isDisposed())
                mDisposable.dispose();
            onComplete();
        }

    }


    /**
     * 写入操作
     *
     * @param bytes 字节流
     */
    public void write(byte[] bytes) {
        mDataList.add(new RecordData(bytes));
    }


    @Override
    public boolean isDisposed() {
        return mDisposable != null && mDisposable.isDisposed();
    }

    @Override
    public void dispose() {
        if (mDisposable != null) mDisposable.dispose();
    }

    private void onComplete() {
        if (outputStream != null) {
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Log.i(TAG, "onComplete: " + mFile);
        synchronized (lock) {
            lock.notifyAll();
        }
    }

    static class RecordData {
        private byte[] bytes;

        RecordData(byte[] bytes) {
            this.bytes = bytes;
        }
    }

    static class SaveComplete {
    }


}
